package com.behelpful.common.integration.iredis.config;

import cn.hutool.core.bean.BeanUtil;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedisPool;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Alay
 * @date 2021-05-02 22:21
 */
@Slf4j
@Configuration
@EnableConfigurationProperties(value = {IRedisProperties.class})
@ComponentScan(basePackages = {"com.behelpful.common.integration.iredis.support"})
public class IRedisConfig {

    @Autowired
    private IRedisProperties redisProperties;
    private JedisPool jedisPool;

    @Bean
    public JedisPoolConfig jedisPoolConfig() {
        JedisPoolConfig config = BeanUtil.copyProperties(redisProperties, JedisPoolConfig.class);
        log.info("[ IRedis ] |- Bean [JedisPoolConfig] Auto Configure.");
        return config;
    }


    @Bean
    @ConditionalOnBean(JedisPoolConfig.class)
    public JedisPool createPool(JedisPoolConfig config) {
        IRedisProperties.Client client = redisProperties.getClients().get(0);
        jedisPool = new JedisPool(config,
                // 地址
                client.getHost(),
                // 端口
                client.getPort(),
                // 连接超时
                client.getConnectionTimeout(),
                // 读取数据超时
                client.getSoTimeout(),
                // 密码
                client.getPassword(),
                // 默认数据库序号
                client.getDatabase(),
                // 客户端名
                client.getClientName(),
                // 是否使用SSL
                client.getSsl(),
                // SSL相关，使用默认
                null, null, null);
        log.info("[ IRedis ] |- Bean [JedisPool] Auto Configure.");
        return jedisPool;
    }


    @Bean
    @ConditionalOnBean(JedisPoolConfig.class)
    public ShardedJedisPool shardedJedisPool(JedisPoolConfig config) {
        List<JedisShardInfo> shards = redisProperties.getClients().stream()
                .map(this::createShardInfo)
                .collect(Collectors.toList());
        ShardedJedisPool shardedJedisPool = new ShardedJedisPool(config, shards);
        log.info("[ IRedis ] |- Bean [ShardedJedisPool] Auto Configure.");
        return shardedJedisPool;
    }


    private JedisShardInfo createShardInfo(IRedisProperties.Client client) {
        JedisShardInfo jedisShardInfo = new JedisShardInfo(
                // 地址
                client.getHost(),
                // 端口
                client.getPort(),
                // 客户端名称
                client.getClientName(),
                // 是否使用SSL
                client.getSsl(),
                // SSL相关，使用默认
                null, null, null);
        jedisShardInfo.setPassword(client.getPassword());
        jedisShardInfo.setConnectionTimeout(client.getConnectionTimeout());
        jedisShardInfo.setSoTimeout(client.getSoTimeout());
        log.info("[ IRedis ] |- Bean [JedisShardInfo] Auto Configure.");
        return jedisShardInfo;
    }


    public void close() {
        jedisPool.close();
    }

    /**
     * Redisson客户端
     *
     * @return
     */
    // @Bean
    @ConditionalOnMissingBean
    public RedissonClient redissonClient() {
        IRedisProperties.Client client = redisProperties.getClients().get(0);
        Config config = new Config();
        config.useSingleServer()
                .setAddress("redis://" + client.getHost() + ":" + client.getPort())
                .setPassword(client.getPassword())
                .setDatabase(0)
                .setConnectionPoolSize(redisProperties.getMaxTotal())
                .setConnectionMinimumIdleSize(2);
        RedissonClient redissonClient = Redisson.create(config);
        log.info("[IRedis] |- Bean [RedissonClient] Auto Configure.");
        return redissonClient;
    }
}